package com.zhengbo.flink.demo.base.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


/**
 * Created by JiaQiang.Zheng on 2016/10/25.
 * 时间工具类
 */
public class DateUtil {

	private DateUtil() {}

	/**
	 * 获取当天凌晨开始时间 yyyy-MM-dd 00:00:00
	 * @return
	 */
	public static Date getCurrentDateInMidnight() {
		String currentDay = DateFormatUtils.format(new Date(), "yyyy-MM-dd");

		String midnight = currentDay + " 00:00:00";

		try {
			return dateTimeThreadLocal.get().parse(midnight);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}



	/**
	 * 获取当天最后的时间 yyyy-MM-dd 23:59:59
	 * @return
	 */
	public static Date getCurrentDateInLastTime() {
		String currentDay = DateFormatUtils.format(new Date(), "yyyy-MM-dd");

		String lastTime = currentDay + " 23:59:59";

		try {
			return dateTimeThreadLocal.get().parse(lastTime);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取date当天的凌晨时间，yyyy-MM-dd 00:00:00
	 * @param date
	 * @return
	 */
	public static Date getDateInMidnigth(Date date){
		String day =DateFormatUtils.format(date, "yyyy-MM-dd");
		String midnight = day + " 00:00:00";
		try {
			return dateTimeThreadLocal.get().parse(midnight);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}


	public static final long ONE_DAY = 24 * 60 * 60 * 1000;


	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	private static final ThreadLocal<SimpleDateFormat> dateTimeThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					DATETIME_FORMAT);
		}
	};
	/**
	 * yyyyMMddHHmmss
	 */
	public static final String LDATETIME_FORMAT = "yyyyMMddHHmmss";

	private static final ThreadLocal<SimpleDateFormat> lDateTimeThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					LDATETIME_FORMAT);
		}
	};

	/**
	 * yyyyMMddHHmmss
	 */
	public static final String LLDATETIME_FORMAT = "yyyyMMddHHmmssSSS";

	private static final ThreadLocal<SimpleDateFormat> llDateTimeThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					LLDATETIME_FORMAT);
		}
	};
	/**
	 * yyyy-MM-dd
	 */
	public static final String DATE_FORMAT = "yyyy-MM-dd";

	private static final ThreadLocal<SimpleDateFormat> dateThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					DATE_FORMAT);
		}
	};
	/**
	 * yyyy年MM月dd日
	 */
	public static final String ADATE_FORMAT = "yyyy年MM月dd日";

	private static final ThreadLocal<SimpleDateFormat> agreementDateThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					ADATE_FORMAT);
		}
	};
	/**
	 * yyyyMMdd
	 */
	public static final String LDATE_FORMAT = "yyyyMMdd";

	private static final ThreadLocal<SimpleDateFormat> lDateThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					LDATE_FORMAT);
		}
	};

	public static  final String PUSH_MSG_TIME ="MM月dd日 HH:mm";
	private static final ThreadLocal<SimpleDateFormat> pushMsgTimeThreadLocal = new ThreadLocal<SimpleDateFormat>() {
		@Override
		protected SimpleDateFormat initialValue() {
			return new SimpleDateFormat(
					PUSH_MSG_TIME);
		}
	};

	/**
	 * @param date
	 * @return yyyyMMdd
	 */
	public static int getLdate(Date date) {
		return Integer.parseInt(formatLShortDate(date));
	}

	/**
	 * @param date
	 * @return yyyyMMddHHmmss
	 */
	public static long getLDateTime(Date date) {
		return Long.parseLong(formatLDateTime(date));
	}

	public static boolean isBefore(Date date1, Date date2) {
		return date2.getTime() - date1.getTime() > 0;
	}

	private static Date add(Date date, int zoom, int amount) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		if (amount == 0) {
			return date;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(zoom, amount);
		return cal.getTime();
	}

	private static Date paser(DateFormat format, String dateString) {
		try {
			return format.parse(dateString);
		} catch (ParseException e) {
			throw new IllegalArgumentException("日期格式错误:" + dateString, e);
		}
	}

	public static String format(DateFormat format, Date date) {
		if (date == null)
			return null;
		return format.format(date);
	}

	/**
	 * yyyy-MM-dd HH:mm:ss
	 *
	 * @param date
	 * @return
	 */
	public static Date parseDateTime(String date) {
		return paser(dateTimeThreadLocal.get(), date);
	}

	/**
	 * yyyyMMddHHmmss
	 *
	 * @param date
	 * @return
	 */
	public static Date parseLDateTime(String date) {
		return paser(lDateTimeThreadLocal.get(), date);
	}


	/**
	 * yyyy-MM-dd
	 *
	 * @param date
	 * @return
	 */
	public static Date parseDate(String date) {
		return paser(dateThreadLocal.get(), date);
	}

	/**
	 * yyyyMMdd
	 * @param date
	 * @return
	 */
	public static Date parseLDate(String date){
		return paser(lDateThreadLocal.get(), date);
	}

	public static Date parseDate(String date, String format) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return paser(new SimpleDateFormat(format), date);
	}

	/**
	 * @param date
	 * @return yyyy-MM-dd HH:mm:ss
	 */
	public static String formatDateTime(Date date) {
		return format(dateTimeThreadLocal.get(), date);
	}

	/**
	 * @param date
	 * @return yyyy年MM月dd日
	 */
	public static String formatAgreementDate(Date date) {
		return format(agreementDateThreadLocal.get(), date);
	}

	/**
	 * @param date
	 * @return yyyy-MM-dd
	 */
	public static String formatDate(Date date) {
		return format(dateThreadLocal.get(), date);
	}

	/**
	 * @param date
	 * @return format
	 */
	public static String formatDate(Date date, String format) {
		return format(new SimpleDateFormat(format), date);
	}

	/**
	 * @param date
	 * @return yyyyMMdd
	 */
	public static String formatLDate(Date date) {
		return format(lDateThreadLocal.get(), date);
	}

	/**
	 * @param date
	 * @return yyyyMMddHHmmss
	 */
	public static String formatLDateTime(Date date) {
		return format(lDateTimeThreadLocal.get(), date);
	}

	public static String formatLLDateTime(Date date) {
		return format(llDateTimeThreadLocal.get(), date);
	}

	/**
	 *
	 * @param date
	 * @return MM月dd日 HH:mm
	 */
	public static String formatPushMsgTime(Date date){
		return format(pushMsgTimeThreadLocal.get(),date);
	}

	/**
	 * @param date
	 * @return yyyyMMdd
	 */
	public static String formatLShortDate(Date date) {
		return format(lDateThreadLocal.get(), date);
	}

	public static Date yesterdayStart() {
		return new Date(todayStart().getTime() - ONE_DAY);
	}

	public static Date yesterdayEnd() {
		return new Date(todayStart().getTime() - 1);
	}

	public static boolean isYesterday(Date startDay) {
		boolean isYesterday = false;
		Date yesterdayStart = yesterdayStart();
		Date yesterdayEnd = yesterdayEnd();
		if (yesterdayStart.getTime() <= startDay.getTime() && yesterdayEnd.getTime() >= startDay.getTime()) {
			isYesterday = true;
		}
		return isYesterday;
	}

	/**
	 * The very beginning of today.
	 *
	 * @return
	 */
	public static Date todayStart() {
		return dayStart(new Date());
	}

	public static Date todayEnd() {
		return dayEnd(new Date());
	}

	public static Date dayStart(Date someday) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(someday);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);

		return calendar.getTime();
	}

	public static Date dayEnd(Date someday) {
		return new Date(dayStart(someday).getTime() + ONE_DAY - 1);
	}

	public static Date zero() {
		return new Date(0);
	}


	/**
	 * 对时间做月份差值计算，获取计算时间那月的第一天
	 *
	 * @param date  基准时间
	 * @param month 多少月
	 * @return yyyy-MM-dd
	 */
	public static Date getFirstDayOfMonthWithAddMonths(Date date, int month) {
		if (date == null)
			return null;

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, month);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);

		return calendar.getTime();
	}

	public static Date addDays(Date date, int amount) {
		return add(date, Calendar.DATE, amount);
	}


//    public static void main(String args[]){
//        String password = "WsgysKpXHWcQvpqDpCy/NP3PBB14x8BcBn1IjNCcSVQU4vJ6KYbklim1cG2VPA5o2+/LLVwptaztvBMGI2hLcw==";
//        try {
//            String pa = ConfigTools.decrypt(password);
//            System.out.println(pa);
//        } catch (Exception e) {
//            //
//        }
//    }
}
